// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
import * as vscode from 'vscode';
import * as fs from 'fs';
import * as path from 'path';
import { exec } from 'child_process';
import { promisify } from 'util';

// 定义函数接口
interface FunctionParam {
    name: string;
    type: string;
    required: boolean;
    description: string;
}

interface FunctionInfo {
    name: string;
    description: string;
    params: FunctionParam[];
    plugin?: string;
}

interface FunctionsJson {
    functions: FunctionInfo[];
}

// 定义全局变量，用于存储提供者实例
let functionManager: FunctionInfoManager | null = null;
let completionProvider: vscode.Disposable | null = null;
let hoverProvider: vscode.Disposable | null = null;

// 定义promisified exec
const execPromise = promisify(exec);

class FunctionInfoManager {
    private functions: Map<string, FunctionInfo> = new Map();

    constructor(functions: FunctionInfo[]) {
        functions.forEach(func => {
            this.functions.set(func.name, func);
        });
    }
    findFunctionByName(name: string): FunctionInfo | undefined {
        return this.functions.get(name);
    }
    getAllFunctions(): FunctionInfo[] {
        return Array.from(this.functions.values());
    }
}

// 读取function.json文件获取函数列表
function loadFunctions(context: vscode.ExtensionContext): FunctionInfo[] {
    try {
        // 首先尝试从工作区的.vscode目录读取function.json
        const workspaceFolders = vscode.workspace.workspaceFolders;
        let functionsPath = path.join(context.extensionPath, 'function.json');
        let content = '';
        
        if (workspaceFolders && workspaceFolders.length > 0) {
            const projectFunctionsPath = path.join(workspaceFolders[0].uri.fsPath, '.vscode', 'function.json');
            
            // 检查项目中的function.json是否存在
            if (fs.existsSync(projectFunctionsPath)) {
                console.log(`Loading functions from project: ${projectFunctionsPath}`);
                content = fs.readFileSync(projectFunctionsPath, 'utf8');
                functionsPath = projectFunctionsPath;
            } else {
                // 如果项目中不存在function.json，使用扩展自带的默认文件
                console.log(`Loading default functions from extension: ${functionsPath}`);
                content = fs.readFileSync(functionsPath, 'utf8');
                
                // 如果.vscode目录不存在，创建它
                const vscodeDir = path.join(workspaceFolders[0].uri.fsPath, '.vscode');
                if (!fs.existsSync(vscodeDir)) {
                    fs.mkdirSync(vscodeDir, { recursive: true });
                }
                
                // 将默认的function.json复制到项目的.vscode目录
                fs.writeFileSync(projectFunctionsPath, content, 'utf8');
                console.log(`Copied default function.json to project: ${projectFunctionsPath}`);
            }
        } else {
            // 如果没有打开工作区，使用扩展自带的默认文件
            console.log(`No workspace opened, loading default functions: ${functionsPath}`);
            content = fs.readFileSync(functionsPath, 'utf8');
        }
        
        const functionsData: FunctionsJson = JSON.parse(content);
        return functionsData.functions;
    } catch (error) {
        console.error('Failed to load function.json:', error);
        return [];
    }
}

// 实现代码补全提供者
class TmakeCompletionProvider implements vscode.CompletionItemProvider {
    private functionManager: FunctionInfoManager;

    constructor(functionManager: FunctionInfoManager) {
        this.functionManager = functionManager;
    }

    provideCompletionItems(
        document: vscode.TextDocument,
        position: vscode.Position,
        token: vscode.CancellationToken
    ): vscode.ProviderResult<vscode.CompletionItem[] | vscode.CompletionList> {
        const isInString = this.isPositionInString(document, position);
        if (isInString) {
            return [];
        }

        const items: vscode.CompletionItem[] = [];

        // 为每个函数创建补全项
        this.functionManager.getAllFunctions().forEach(func => {
            // 使用Function类型的补全项，确保显示函数图标而非abc文本图标
            const item = new vscode.CompletionItem(func.name, vscode.CompletionItemKind.Function);
            
            // 确保函数有正确的排序权重
            item.sortText = '0'; // 让我们的函数补全项始终排在最前面
            
            // 设置函数文档和插入文本 - 确保包含括号
            const paramsStr = func.params.length > 0 
                ? func.params.map((p, index) => `\${${index + 1}:${p.name}}`).join(', ')
                : '';
            
            // 重要：确保补全项包含括号
            item.insertText = new vscode.SnippetString(`${func.name}(${paramsStr})`);
            item.preselect = true;
            
            // 设置详细的文档提示
            let documentation = new vscode.MarkdownString();
            documentation.appendMarkdown(`## ${func.name}\n`);
            documentation.appendMarkdown(`**描述**: ${func.description}\n\n`);
            
            if (func.params.length > 0) {
                documentation.appendMarkdown(`**参数**:\n`);
                func.params.forEach(param => {
                    documentation.appendMarkdown(`- \`${param.name}\` (${param.type})${param.required ? ' (必需)' : ''}: ${param.description}\n`);
                });
            }
            
            item.documentation = documentation;
            
            // 添加筛选器，确保所有中文函数名都能被正确识别
            item.filterText = func.name;
            
            items.push(item);
        });

        return new vscode.CompletionList(items, true); // 设置为incomplete，确保VS Code总是显示我们的补全项
    }
    
    // 检查位置是否在字符串内
    private isPositionInString(document: vscode.TextDocument, position: vscode.Position): boolean {
        const line = document.lineAt(position.line).text;
        let inString = false;
        let stringChar = '';
        let escaped = false;
        
        for (let i = 0; i < position.character; i++) {
            const char = line[i];
            
            if (escaped) {
                escaped = false;
                continue;
            }
            
            if (char === '\\') {
                escaped = true;
                continue;
            }
            
            if ((char === '"' || char === "'") && (!inString || char === stringChar)) {
                inString = !inString;
                if (inString) {
                    stringChar = char;
                } else {
                    stringChar = '';
                }
            }
        }
        
        return inString;
    }
}

// 实现悬停提示提供者 - 当鼠标悬停在函数名上时显示函数信息
class TmakeHoverProvider implements vscode.HoverProvider {
    private functionManager: FunctionInfoManager;

    constructor(functionManager: FunctionInfoManager) {
        this.functionManager = functionManager;
    }

    provideHover(
        document: vscode.TextDocument,
        position: vscode.Position,
        token: vscode.CancellationToken
    ): vscode.ProviderResult<vscode.Hover> {
        // 获取当前位置的单词
        const range = document.getWordRangeAtPosition(position);
        if (!range) {
            return undefined;
        }

        const word = document.getText(range);
        
        // 查找函数信息
        const funcInfo = this.functionManager.findFunctionByName(word);
        if (!funcInfo) {
            return undefined;
        }

        // 创建悬停内容
        const markdown = new vscode.MarkdownString();
        markdown.appendMarkdown(`## ${funcInfo.name}\n`);
        markdown.appendMarkdown(`**描述**: ${funcInfo.description}\n\n`);
        
        if (funcInfo.params.length > 0) {
            markdown.appendMarkdown(`**参数**:\n`);
            funcInfo.params.forEach(param => {
                markdown.appendMarkdown(`- \`${param.name}\` (${param.type})${param.required ? ' (必需)' : ''}: ${param.description}\n`);
            });
        }

        return new vscode.Hover(markdown);
    }
}

async function reloadFunctionsInternal(context: vscode.ExtensionContext): Promise<void> {
    try {
        // 使用固定路径的index.ts生成新的function.json
        const workspaceFolders = vscode.workspace.workspaceFolders;
        if (workspaceFolders && workspaceFolders.length > 0) {
            try {
                const projectRoot = workspaceFolders[0].uri.fsPath;
                await execPromise('tmake --generate-functions', { cwd: projectRoot });
                vscode.window.showInformationMessage('成功执行tmake生成函数描述文件');
            } catch (error) {
                vscode.window.showWarningMessage('执行tmake命令失败，将尝试直接加载现有function.json文件');
                console.warn('Failed to execute tmake command:', error);
            }
        }
        
        // 无论tmake执行是否成功，都尝试重新加载function.json
        const functions = loadFunctions(context);
        
        // 清理旧的提供者
        if (completionProvider) {
            completionProvider.dispose();
        }
        if (hoverProvider) {
            hoverProvider.dispose();
        }
        
        // 重新初始化函数管理器和提供者
        functionManager = new FunctionInfoManager(functions);
        
        // 注册新的代码补全提供者
        completionProvider = vscode.languages.registerCompletionItemProvider(
            'tmake',
            new TmakeCompletionProvider(functionManager),
            ...Array.from('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_(){}[].,;:!@#$%^&*+-='),
            '' 
        );
        
        // 注册新的悬停提示提供者
        hoverProvider = vscode.languages.registerHoverProvider(
            'tmake',
            new TmakeHoverProvider(functionManager)
        );
        
        vscode.window.showInformationMessage(`成功重载${functions.length}个函数描述`);
    } catch (error) {
        vscode.window.showErrorMessage(`重载函数描述失败: ${(error as Error).message}`);
        console.error('Failed to reload functions:', error);
    }
}

// This method is called when your extension is activated
// Your extension is activated the very first time the command is executed
export function activate(context: vscode.ExtensionContext) {

    // Use the console to output diagnostic information (console.log) and errors (console.error)
    // This line of code will only be executed once when your extension is activated
    console.log('Congratulations, your extension "tmake" is now active!');

    // 加载函数列表并初始化函数管理器
    const functions = loadFunctions(context);
    console.log(`Loaded ${functions.length} functions from function.json`);
    functionManager = new FunctionInfoManager(functions);
    
    // 注册代码补全提供者
    completionProvider = vscode.languages.registerCompletionItemProvider(
        'tmake',
        new TmakeCompletionProvider(functionManager),
        ...Array.from('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_(){}[].,;:!@#$%^&*+-='),
		'' 
    );
    
    // 注册悬停提示提供者 - 当鼠标悬停在函数名上时显示函数信息
    hoverProvider = vscode.languages.registerHoverProvider(
        'tmake',
        new TmakeHoverProvider(functionManager)
    );

    // 注册重载函数命令
    const reloadFunctionsCommand = vscode.commands.registerCommand('tmake.reloadFunctions', () => {
        reloadFunctionsInternal(context);
    });

    // 注册编译项目命令
    const compileProjectCommand = vscode.commands.registerCommand('tmake.compileProject', async () => {
        try {
            const workspaceFolders = vscode.workspace.workspaceFolders;
            if (!workspaceFolders || workspaceFolders.length === 0) {
                vscode.window.showErrorMessage('没有打开的工作区');
                return;
            }
            
            const projectRoot = workspaceFolders[0].uri.fsPath;
            const channel = vscode.window.createOutputChannel('Tmake编译');
            channel.clear();
            channel.show(true);
            channel.appendLine(`开始编译项目: ${projectRoot}`);
            
            // 创建任务进度指示器
            const progressOptions = {
                location: vscode.ProgressLocation.Notification,
                title: 'Tmake编译',
                cancellable: true
            };
            
            await vscode.window.withProgress(progressOptions, async (progress, token) => {
                progress.report({ increment: 0, message: '准备编译环境...' });
                
                token.onCancellationRequested(() => {
                    channel.appendLine('编译任务已取消');
                });
                try {
                    progress.report({ increment: 10, message: '查找tmake命令...' });
                    const compileCommand = 'tmake';
                    
                    progress.report({ increment: 20, message: '开始编译...' });
                    
                    // 执行编译并实时显示输出
                    const process = require('child_process').spawn(compileCommand, [], {
                        cwd: projectRoot,
                        shell: true
                    });
                    
                    return new Promise<void>((resolve, reject) => {
                        process.stdout.on('data', (data: Buffer) => {
                            const output = data.toString();
                            channel.append(output);
                            progress.report({ increment: 0, message: '编译中...' });
                        });
                        
                        process.stderr.on('data', (data: Buffer) => {
                            const error = data.toString();
                            channel.append(error);
                            console.error('编译错误:', error);
                        });
                        
                        process.on('close', (code: number) => {
                            if (code === 0) {
                                progress.report({ increment: 100, message: '编译完成' });
                                channel.appendLine('\n编译成功完成！');
                                vscode.window.showInformationMessage('项目编译成功');
                                resolve();
                            } else {
                                channel.appendLine(`\n编译失败，退出码: ${code}`);
                                vscode.window.showErrorMessage('项目编译失败，请查看输出窗口');
                                reject(new Error(`编译失败，退出码: ${code}`));
                            }
                        });
                        
                        token.onCancellationRequested(() => {
                            process.kill();
                            reject(new Error('编译被用户取消'));
                        });
                    });
                } catch (error) {
                    const errMessage = (error as Error).message;
                    channel.appendLine(`编译错误: ${errMessage}`);
                    throw error;
                }
            });
        } catch (error) {
            vscode.window.showErrorMessage(`编译项目失败: ${(error as Error).message}`);
        }
    });

    // 注册创建项目命令
    const createProjectCommand = vscode.commands.registerCommand('tmake.createProject', async () => {
        try {
            const folderUri = await vscode.window.showOpenDialog({
                canSelectFolders: true,
                canSelectFiles: false,
                canSelectMany: false,
                openLabel: '选择项目位置'
            });
            
            if (!folderUri || folderUri.length === 0) {
                return; // 用户取消了选择
            }
            
            const projectPath = folderUri[0].fsPath;
            
            // 询问项目名称
            const projectName = await vscode.window.showInputBox({
                prompt: '请输入项目名称',
                placeHolder: 'my-tmake-project',
                validateInput: (value) => {
                    if (!value || value.trim() === '') {
                        return '项目名称不能为空';
                    }
                    return null;
                }
            });
            
            if (!projectName) {
                return; // 用户取消了输入
            }
            
            const channel = vscode.window.createOutputChannel('Tmake创建项目');
            channel.clear();
            channel.show(true);
            channel.appendLine(`开始创建项目: ${projectName} 在 ${projectPath}`);
            
            // 创建任务进度指示器
            await vscode.window.withProgress({
                location: vscode.ProgressLocation.Notification,
                title: '创建Tmake项目',
                cancellable: true
            }, async (progress, token) => {
                progress.report({ increment: 0, message: '创建项目...' });
                
                try {
                    // 直接使用tmake create命令创建项目
                    const createCommand = `tmake create ${projectName}`;
                    
                    progress.report({ increment: 50, message: '执行创建命令...' });
                    
                    // 在选择的目录下执行tmake create命令并实时显示输出
                    const process = require('child_process').spawn(createCommand, [], {
                        shell: true,
                        cwd: projectPath
                    });
                    
                    return new Promise<void>((resolve, reject) => {
                        process.stdout.on('data', (data: Buffer) => {
                            const output = data.toString();
                            channel.append(output);
                            progress.report({ increment: 0, message: '创建中...' });
                        });
                        
                        process.stderr.on('data', (data: Buffer) => {
                            const error = data.toString();
                            channel.append(error);
                            console.error('创建错误:', error);
                        });
                        
                        process.on('close', (code: number) => {
                            if (code === 0) {
                                progress.report({ increment: 90, message: '项目创建完成' });
                                channel.appendLine('\n项目创建成功！');
                                
                                // 询问是否打开新创建的项目
                                vscode.window.showInformationMessage(
                                    `项目 ${projectName} 创建成功！是否打开新项目？`,
                                    '是',
                                    '否'
                                ).then(selection => {
                                    if (selection === '是') {
                                        const newProjectPath = path.join(projectPath, projectName);
                                        const folderUri = vscode.Uri.file(newProjectPath);
                                        vscode.commands.executeCommand('vscode.openFolder', folderUri);
                                    }
                                });
                                
                                resolve();
                            } else {
                                channel.appendLine(`\n项目创建失败，退出码: ${code}`);
                                vscode.window.showErrorMessage(`项目创建失败，请查看输出窗口`);
                                reject(new Error(`项目创建失败，退出码: ${code}`));
                            }
                        });
                        
                        token.onCancellationRequested(() => {
                            process.kill();
                            reject(new Error('项目创建被用户取消'));
                        });
                    });
                } catch (error) {
                    const errMessage = (error as Error).message;
                    channel.appendLine(`创建项目失败: ${errMessage}`);
                    throw error;
                }
            });
            
            vscode.window.showInformationMessage(`项目 ${projectName} 创建成功！`);
        } catch (error) {
            vscode.window.showErrorMessage(`创建项目失败: ${(error as Error).message}`);
        }
    });

    // 注册清理项目命令
    const cleanProjectCommand = vscode.commands.registerCommand('tmake.cleanProject', async () => {
        try {
            const workspaceFolders = vscode.workspace.workspaceFolders;
            if (!workspaceFolders || workspaceFolders.length === 0) {
                vscode.window.showErrorMessage('没有打开的工作区');
                return;
            }
            
            const projectRoot = workspaceFolders[0].uri.fsPath;
            const channel = vscode.window.createOutputChannel('Tmake清理');
            channel.clear();
            channel.show(true);
            channel.appendLine(`开始清理项目: ${projectRoot}`);
            
            // 创建任务进度指示器
            await vscode.window.withProgress({
                location: vscode.ProgressLocation.Notification,
                title: '清理Tmake项目',
                cancellable: true
            }, async (progress, token) => {
                progress.report({ increment: 0, message: '开始清理...' });
                
                token.onCancellationRequested(() => {
                    channel.appendLine('清理任务已取消');
                });
                
                try {
                    progress.report({ increment: 20, message: '查找tmake命令...' });
                    
                    const cleanCommandUsingIndex = 'tmake clean';
                    
                    progress.report({ increment: 40, message: '执行清理...' });
                    try {
                        await execPromise(cleanCommandUsingIndex, { cwd: projectRoot });
                        progress.report({ increment: 80, message: '清理完成...' });
                        channel.appendLine('\n项目清理成功！');
                    } catch (execError) {
                        // 如果tmake清理失败，尝试手动清理常见的输出目录
                        progress.report({ increment: 60, message: 'tmake清理失败，尝试手动清理...' });
                        channel.appendLine('tmake清理失败，尝试手动清理常见输出目录...');
                        
                        // 尝试清理常见的输出目录
                        const outputDirs = ['./output', './dist', './build'];
                        for (const dir of outputDirs) {
                            const fullPath = path.join(projectRoot, dir);
                            if (fs.existsSync(fullPath)) {
                                try {
                                    fs.rmSync(fullPath, { recursive: true, force: true });
                                    channel.appendLine(`已删除目录: ${dir}`);
                                } catch (rmError) {
                                    channel.appendLine(`删除 ${dir} 失败: ${(rmError as Error).message}`);
                                }
                            }
                        }
                        
                        progress.report({ increment: 80, message: '手动清理完成...' });
                    }
                    progress.report({ increment: 100, message: '清理完成' });
                    vscode.window.showInformationMessage('项目清理完成');
                } catch (error) {
                    channel.appendLine(`\n清理项目失败: ${(error as Error).message}`);
                    throw error;
                }
            });
        } catch (error) {
            vscode.window.showErrorMessage(`清理项目失败: ${(error as Error).message}`);
        }
    });

    // 添加所有提供者和命令到订阅列表，确保在扩展停用时能够正确清理
    context.subscriptions.push(reloadFunctionsCommand);
    context.subscriptions.push(compileProjectCommand);
    context.subscriptions.push(createProjectCommand);
    context.subscriptions.push(cleanProjectCommand);
    context.subscriptions.push(completionProvider);
    context.subscriptions.push(hoverProvider);
}

// This method is called when your extension is deactivated
export function deactivate() {}
